package com.fxcalibre.hibernate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.LogicalExpression;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

public class GenericCriteria
{
	public static final int OP_IGUAL = 1;
	public static final int OP_NO_IGUAL = 2;
	public static final int OP_MAYOR = 3;
	public static final int OP_MAYOR_IGUAL = 4;
	public static final int OP_MENOR = 5;
	public static final int OP_MENOR_IGUAL = 6;
	public static final int OP_IS_NOT_NULL = 7;
	public static final int OP_IS_NULL = 8;
	public static final int ASCENDENTE = 1;
	public static final int DESCENDENTE = 2;
	private String entity;
	private ArrayList<Criterion> where = new ArrayList<Criterion>();
	private ArrayList<Order> order = new ArrayList<Order>();
	private Map<String, Criterion> subcriterias = new HashMap<String, Criterion>();

	public GenericCriteria()
	{
	}

	public GenericCriteria(String entidad)
	{
		setEntity(entidad);
	}

	public String getEntity()
	{
		return entity;
	}

	public void setEntity(String entity)
	{
		this.entity = entity;
	}

	public List<Criterion> getWhere()
	{
		return this.where;
	}

	public List<Order> getOrder()
	{
		return this.order;
	}

	public void addCriterion(String campo, int operacion, int valor)
	{
		addCriterion(campo, operacion, new Integer(valor));
	}

	public void addCriterion(String campo, int operacion, Object valor)
	{
		this.where.add((Criterion) createCriterion(campo, operacion, valor));
	}

	public void addCriterion(String campo1, String campo2, int operacion)
	{
		switch (operacion)
		{
		case 7:
			Criterion c1 = Restrictions.isNotNull(campo1);
			Criterion c2 = Restrictions.isNotNull(campo2);
			LogicalExpression le = Restrictions.or(c1, c2);

			this.where.add(le);
		}
	}

	public void addSubcriteria(String relationShip, String field, int operator, Object value)
	{
		subcriterias.put(relationShip, createCriterion(field, operator, value));
	}

	private Criterion createCriterion(String field, int operator, Object value)
	{
		switch (operator)
		{
		case 1:
			return Restrictions.eq(field, value);
		case 2:
			return Restrictions.ne(field, value);
		case 3:
			return Restrictions.gt(field, value);
		case 4:
			return Restrictions.ge(field, value);
		case 5:
			return Restrictions.lt(field, value);
		case 6:
			return Restrictions.le(field, value);
		case 7:
			return Restrictions.isNotNull(field);
		case 8:
			return Restrictions.isNull(field);
		}

		return null;
	}

	public void addOrder(String campo, int orden)
	{
		switch (orden)
		{
		case 1:
			this.order.add(Order.asc(campo));
			break;
		case 2:
			this.order.add(Order.desc(campo));
		}
	}

	public void addOrder(String atributoOrdenacion, String sentidoOrdenacion, String defaultAtributoOrdenacion)
	{
		String atributo = atributoOrdenacion;
		String sentido = sentidoOrdenacion;
		if ((sentidoOrdenacion == null) || ((!sentidoOrdenacion.equalsIgnoreCase("asc")) && (!sentidoOrdenacion.equalsIgnoreCase("desc"))))
		{
			sentido = "asc";
		}
		if ((atributoOrdenacion == null) || (atributoOrdenacion.equals("")) || (atributoOrdenacion.equalsIgnoreCase("null")))
		{
			atributo = defaultAtributoOrdenacion;
		}
		addOrder(atributo, "desc".equalsIgnoreCase(sentido) ? 2 : 1);
	}

	public static String getOrderByClause(String atributoOrdenacion, String sentidoOrdenacion, String defaultAtributoOrdenacion)
	{
		String atributo = atributoOrdenacion;
		String sentido = sentidoOrdenacion;
		if ((sentidoOrdenacion == null) || ((!sentidoOrdenacion.equalsIgnoreCase("asc")) && (!sentidoOrdenacion.equalsIgnoreCase("desc"))))
		{
			sentido = "asc";
		}
		if ((atributoOrdenacion == null) || (atributoOrdenacion.equals("")) || (atributoOrdenacion.equalsIgnoreCase("null")))
		{
			atributo = defaultAtributoOrdenacion;
		}
		return " ORDER BY " + atributo + " " + sentido;
	}

	public Map<String, Criterion> getSubcriterias()
	{
		return subcriterias;
	}

}